const express = require('express');
const ModbusRTU = require("modbus-serial");
const cors = require('cors');

const app = express();
const port = 3001;

// 中间件
app.use(cors());
app.use(express.json());

// 创建Modbus客户端实例
let client = null;

// PLC连接实例
let plcConnection = null;

// 辅助函数：将字符串转换为寄存器值
function stringToRegisters(str) {
  const registers = [];
  // 确保字符串长度为偶数，如果为奇数则补空格
  const paddedStr = str.length % 2 === 0 ? str : str + ' ';
  
  for (let i = 0; i < paddedStr.length; i += 2) {
    const char1 = paddedStr[i] ? paddedStr.charCodeAt(i) : 0;
    const char2 = paddedStr[i + 1] ? paddedStr.charCodeAt(i + 1) : 0;
    // 低字节在前，高字节在后
    registers.push((char2 << 8) | char1);
  }
  
  return registers;
}

// 辅助函数：创建PLC连接
async function createConnection(config) {
  if (client && client.isOpen) {
    client.close();
  }
  
  client = new ModbusRTU();
  
  try {
    await client.connectTCP(config.ipAddress, { port: config.port });
    client.setID(1); // 默认设备ID为1
    console.log(`已连接到PLC: ${config.ipAddress}:${config.port}`);
    plcConnection = config; // 保存连接配置
    return true;
  } catch (error) {
    console.error('PLC连接失败:', error.message);
    throw error;
  }
}

// API: 测试PLC连接并建立连接
app.post('/api/plc/test-connection', async (req, res) => {
  try {
    const { ipAddress, port, writeAddress } = req.body;
    
    if (!ipAddress || !port || !writeAddress) {
      return res.json({
        success: false,
        message: '请提供完整的PLC配置信息（IP、端口、写入地址）'
      });
    }
    
    console.log(`建立PLC连接: ${ipAddress}:${port}, 写入地址: ${writeAddress}`);
    
    // 创建连接
    await createConnection({ ipAddress, port: parseInt(port), writeAddress: parseInt(writeAddress) });
    
    // 测试写入地址是否可访问
    try {
      await client.readHoldingRegisters(parseInt(writeAddress), 1);
      console.log(`写入地址 ${writeAddress} 可访问`);
    } catch (error) {
      console.warn(`无法读取地址 ${writeAddress}:`, error.message);
    }
    
    res.json({
      success: true,
      message: 'PLC连接建立成功，可以开始扫码'
    });
    
  } catch (error) {
    console.error('PLC连接失败:', error.message);
    res.json({
      success: false,
      message: error.message || '连接失败'
    });
  }
});

// API: 写入条码到PLC
app.post('/api/plc/write-barcode', async (req, res) => {
  try {
    const { barcode } = req.body;
    
    if (!barcode) {
      return res.json({
        success: false,
        message: '请提供条码数据'
      });
    }
    
    if (!plcConnection || !client || !client.isOpen) {
      return res.json({
        success: false,
        message: '请先建立PLC连接'
      });
    }
    
    console.log(`写入条码到PLC地址${plcConnection.writeAddress}: ${barcode}`);
    
    // 1. 将条码转换为寄存器值
    const barcodeRegisters = stringToRegisters(barcode);
    console.log(`条码转换结果: ${barcode} -> [${barcodeRegisters.join(', ')}]`);
    
    // 2. 写入条码到指定地址
    await client.writeRegisters(plcConnection.writeAddress, barcodeRegisters);
    console.log(`条码已写入地址 ${plcConnection.writeAddress}`);
    
    res.json({
      success: true,
      message: `条码已成功写入PLC`,
      data: {
        barcode: barcode,
        writeAddress: plcConnection.writeAddress,
        timestamp: new Date().toISOString()
      }
    });
    
  } catch (error) {
    console.error('写入条码失败:', error.message);
    
    res.json({
      success: false,
      message: error.message || '写入条码失败'
    });
  }
});

// API: 断开PLC连接
app.post('/api/plc/disconnect', async (req, res) => {
  try {
    if (client && client.isOpen) {
      client.close();
      console.log('PLC连接已断开');
    }
    
    plcConnection = null;
    
    res.json({
      success: true,
      message: 'PLC连接已断开'
    });
    
  } catch (error) {
    console.error('断开连接失败:', error.message);
    res.json({
      success: false,
      message: error.message || '断开连接失败'
    });
  }
});

// 健康检查
app.get('/api/health', (req, res) => {
  res.json({
    status: 'ok',
    message: 'PLC服务运行正常',
    timestamp: new Date().toISOString()
  });
});

// 启动服务器
app.listen(port, () => {
  console.log(`PLC条码服务已启动，监听端口 ${port}`);
  console.log(`健康检查: http://localhost:${port}/api/health`);
  console.log('服务功能:');
  console.log('- 建立PLC连接: POST /api/plc/test-connection');
  console.log('- 写入条码: POST /api/plc/write-barcode');
  console.log('- 断开连接: POST /api/plc/disconnect');
});

// 优雅关闭
process.on('SIGINT', () => {
  console.log('\n正在关闭PLC服务...');
  if (client && client.isOpen) {
    client.close();
    console.log('PLC连接已关闭');
  }
  process.exit(0);
});

module.exports = app; 